---
id: clayobj
title: 29. 粘土对象
sidebar_label: 29. 粘土对象
---

:::important 版本说明

以下内容仅限 `Furion 2.1.12 +` 版本使用。

:::

## 29.1 关于粘土对象

粘土对象是 `Furion` 框架自创的一种概念，是一种可以模拟弱语言特性的对象，类似 `Javascript` 一样操作对象。只需通过 `Clay` 类初始化即可。

**为什么起名为 “粘土” 呢？因为这个对象可以自由的添加属性，移除属性，又可以固化成任何对象，具有可拓展、可塑造的特点。**

### 29.1.1 使用场景

粘土对象常用于需要动态构建对象的地方，如 `CMS` 系统的 `ViewModel`，或者运行时创建一个新的对象，或者请求第三方 `API` 情况。

### 29.1.2 关于性能

粘土性能实际上并不高效，但是性能也并不低下，只不过略输于强类型调用。什么时候使用可以看以上的【使用场景】。

## 29.2 `Clay` 对象

`Clay` 对象是继承自 `DynamicObject` 的一个特殊对象，提供了像弱语言一样操作对象的方法及索引。

## 29.3 如何使用

### 29.3.1 创建一个对象

```cs
// 创建一个空的粘土对象
dynamic clay = new Clay();

// 从现有的对象创建
dynamic clay2 = Clay.Object(new {});

// 从 json 字符串创建，可用于第三方 API 对接，非常有用
dynamic clay3 = Clay.Parse(@"{""foo"":""json"", ""bar"":100, ""nest"":{ ""foobar"":true } }");
```

### 29.3.2 读取/获取属性

```cs
dynamic clay = Clay.Object(new
{
    Foo = "json",
    Bar = 100,
    Nest = new
    {
        Foobar = true
    }
});

var r1 = clay.Foo; // "json" - string类型
var r2 = clay.Bar; // 100 - double类型
var r3 = clay.Nest.Foobar; // true - bool类型
var r4 = clay["Nest"]["Foobar"]; // 还可以和 Javascript 一样通过索引器获取
```

### 29.3.3 新增属性

```cs
dynamic clay = Clay.Object(new
{
    Foo = "json",
    Bar = 100,
    Nest = new
    {
        Foobar = true
    }
});

// 新增
clay.Arr = new string[] { "NOR", "XOR" }; // 添加一个数组
clay.Obj1 = new City { }; // 新增一个实例对象
clay.Obj2 = new { Foo = "abc", Bar = 100 }; // 新增一个匿名类
```

### 29.3.4 更新属性值

```cs
dynamic clay = Clay.Object(new
{
    Foo = "json",
    Bar = 100,
    Nest = new
    {
        Foobar = true
    }
});

// 更新
clay.Foo = "Furion";
clay["Nest"].Foobar = false;
clay.Nest["Foobar"] = true;
```

### 29.3.5 删除属性

```cs
dynamic clay = Clay.Object(new
{
    Foo = "json",
    Bar = 100,
    Nest = new
    {
        Foobar = true
    },
    Arr = new string[] { "NOR", "XOR" }
});

// 删除操作
clay.Delete("Foo"); // 通过 Delete 方法删除
clay.Arr.Delete(0); // 支持数组 Delete 索引删除
clay("Bar");    // 支持直接通过对象作为方法删除
clay.Arr(1);    // 支持数组作为方法删除
```

### 29.3.6 判断属性是否存在

```cs
dynamic clay = Clay.Object(new
{
    Foo = "json",
    Bar = 100,
    Nest = new
    {
        Foobar = true
    },
    Arr = new string[] { "NOR", "XOR" }
});

// 判断属性是否存在
var a = clay.IsDefined("Foo"); // true
var b = clay.IsDefined("Foooo"); // false
var c = clay.Foo(); // true
var d = clay.Foooo(); // false;
```

### 29.3.7 遍历对象

```cs
dynamic clay = Clay.Object(new
{
    Foo = "json",
    Bar = 100,
    Nest = new
    {
        Foobar = true
    },
    Arr = new string[] { "NOR", "XOR" }
});

// 遍历数组
foreach (string item in clay.Arr)
{
    Console.WriteLine(item); // NOR, XOR
}

// 遍历整个对象属性及值，类似 JavaScript 的 for (var p in obj)
foreach (KeyValuePair<string, dynamic> item in clay)
{
    Console.WriteLine(item.Key + ":" + item.Value); // Foo:json, Bar: 100, Nest: { "Foobar":true}, Arr:["NOR","XOR"]
}
```

### 29.3.8 转换成具体对象

```cs
dynamic clay = new Clay();
clay.Arr = new string[] { "Furion", "Fur" };

// 数组转换示例
var a1 = clay.Arr.Deserialize<string[]>(); // 通过 Deserialize 方法
var a2 = (string[])clay.Arr;    // 强制转换
string[] a3 = clay.Arr; // 声明方式

// 对象转换示例
clay.City = new City { Id = 1, Name = "中山市" };
var c1 = clay.City.Deserialize<City>(); // 通过 Deserialize 方法
var c2 = (City)clay.City;    // 强制转换
City c3 = clay.City; // 声明方式
```

### 29.3.9 固化粘土

固化粘土在很多时候和序列化很像，但是如果直接调用 `Deserialize<object>` 或 `Deserialize<dynamic>` 无法返回实际类型，所以就有了固化类型的功能，如：

```cs
// 返回 object
var obj = clay.Solidify();

// 返回 dynamic
var obj1 = clay.Solidify<dynamic>();

// 返回其他任意类型
var obj2 = clay.Solidify<City>();
```

### 29.3.10 输出 `JSON`

```cs
dynamic clay = Clay.Object(new
{
    Foo = "json",
    Bar = 100,
    Nest = new
    {
        Foobar = true
    },
    Arr = new string[] { "NOR", "XOR" }
});

// 输出 JSON
var json = clay.ToString(); // "{\"Foo\":\"json\",\"Bar\":100,\"Nest\":{\"Foobar\":true},\"Arr\":[\"NOR\",\"XOR\"]}"
```

### 29.3.11 输出 `XML` 对象

```cs
dynamic clay = Clay.Object(new
{
    Foo = "json",
    Bar = 100,
    Nest = new
    {
        Foobar = true
    },
    Arr = new string[] { "NOR", "XOR" }
});

// 输出 XElement
var xml = clay.XmlElement;
```

### 29.3.12 关键字处理

```cs
dynamic clay = new Clay();
clay.@int = 1;
clay.@event = "事件";
```

### 29.3.13 转换成字典类型

```cs
dynamic clay = Clay.Object(new { name = "张三" });
clay.name = "百小僧";
Dictionary<string, object> parms = clay.ToDictionary();
```

## 29.4 反馈与建议

:::note 与我们交流

给 Furion 提 [Issue](https://gitee.com/dotnetchina/Furion/issues/new?issue)。

:::
